#define DEBUG
#include <cstdio>

using namespace std;

const int maxn=100000, maxm=100000;

int min(int a, int b) {
  return a<b ? a : b;
}

int max(int a, int b) {
  return a>b ? a : b;
}

class Tree {
public:
  int n, m, ind[maxn+1], to[2*maxn-1], link[2*maxn-1], dfn[maxn+1], size[maxn+1];

  void addSide(int u, int v) {
    m++;
    to[m] = v;
    link[m] = ind[u];
    ind[u] = m;
  }

  void build(int o, int fa) {
    dfn[o] = ++dfn[0];
    size[o] = 1;
    for (int i=ind[o]; i; i=link[i]) {
      if (to[i]!=fa) {
	build(to[i], o);
	size[o] += size[to[i]];
      }
    }
  }
};

class SegmentTree {
public:
  int mark[4*maxn+1], val[4*maxn+1];

  void add(int o, int l, int r, int tl, int tr, int v) {
    if (l==tl && r==tr) {
      mark[o]+=v;
      if (mark[o]) {
	val[o] = r-l+1;
      } else {
	if (l==r) {
	  val[o] = 0;
	} else {
	  val[o] = val[o*2]+val[o*2+1];
	}
      }
    } else {
      int mid=(l+r)/2;
      if (tl<=mid && tr>=l) {
	add(o*2, l, mid, max(tl, l), min(tr, mid), v);
      }
      if (tl<=r && tr>mid) {
	add(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r), v);
      }
      if (!mark[o]) {
	val[o] = val[o*2]+val[o*2+1];
      }
    }
  }

  int get(int o, int l, int r, int tl, int tr) {
    if (mark[o]) {
      return tr-tl+1;
    }
    if (l==tl && r==tr) {
      return val[o];
    } else {
      int mid=(l+r)/2, ret=0;
      if (tl<=mid && tr>=l) {
	ret += get(o*2, l, mid, max(tl, l), min(tr, mid));
      }
      if (tl<=r && tr>mid) {
	ret += get(o*2+1, mid+1, r, max(tl, mid+1), min(tr, r));
      }
      return ret;
    }
  }
};

void sort(int a[][4], int l, int r) {
  int i=l, j=r, mid=a[(l+r)/2][0], temp;
  for (; i<=j; ) {
    for (; a[j][0]>mid; j--);
    for (; a[i][0]<mid; i++);
    if (i<=j) {
      for (int k=0; k<4; k++) {
	temp=a[i][k], a[i][k]=a[j][k], a[j][k]=temp;
      }
      i++, j--;
    }
  }
  if (i<r) {
    sort(a, i, r);
  }
  if (j>l) {
    sort(a, l, j);
  }
}

void addRect(int x1, int y1, int x2, int y2, int line[2*maxn+8*maxm+1][4]) {
  if (x1<=x2 && y1<=y2) {
    line[++line[0][0]][0] = x1;
    line[line[0][0]][1] = y1;
    line[line[0][0]][2] = y2;
    line[line[0][0]][3] = 1;
    line[++line[0][0]][0] = x2+1;
    line[line[0][0]][1] = y1;
    line[line[0][0]][2] = y2;
    line[line[0][0]][3] = -1;
  }
}

int main() {
  freopen("tree.in", "r", stdin);
  freopen("tree.out", "w", stdout);

  static Tree g;
  int n, m;
  scanf("%d %d", &n, &m);
  for (int i=1; i<n; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    g.addSide(u, v);
    g.addSide(v, u);
  }
  g.build(1, 0);

  static int line[2*maxn+8*maxm+1][4];
  for (int i=1; i<=n; i++) {
    addRect(i, i, i, i, line);
  }
  for (int i=1; i<=m; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    if (g.dfn[x]<=g.dfn[y] && g.dfn[x]+g.size[x]>g.dfn[y]) {
      addRect(1, g.dfn[y], g.dfn[x], g.dfn[y]+g.size[y]-1, line);
      addRect(g.dfn[y], 1, g.dfn[y]+g.size[y]-1, g.dfn[x], line);
      addRect(g.dfn[x]+g.size[x], g.dfn[y], n, g.dfn[y]+g.size[y]-1, line);
      addRect(g.dfn[y], g.dfn[x]+g.size[x], g.dfn[y]+g.size[y]-1, n, line);
    } else if (g.dfn[y]<=g.dfn[x] && g.dfn[y]+g.size[y]>g.dfn[x]) {
      addRect(1, g.dfn[x], g.dfn[y], g.dfn[x]+g.size[x]-1, line);
      addRect(g.dfn[x], 1, g.dfn[x]+g.size[x]-1, g.dfn[y], line);
      addRect(g.dfn[y]+g.size[y], g.dfn[x], n, g.dfn[x]+g.size[x]-1, line);
      addRect(g.dfn[x], g.dfn[y]+g.size[y], g.dfn[x]+g.size[x]-1, n, line);
    } else {
      addRect(g.dfn[x], g.dfn[y], g.dfn[x]+g.size[x]-1, g.dfn[y]+g.size[y]-1, line);
      addRect(g.dfn[y], g.dfn[x], g.dfn[y]+g.size[y]-1, g.dfn[x]+g.size[x]-1, line);
    }
  }
  sort(line, 1, line[0][0]);

  static SegmentTree sgt;
  int ans=n*n;
  for (int i=1, j=1; i<=n; i++) {
    for (; j<=line[0][0] && line[j][0]<=i; j++) {
      sgt.add(1, 1, n, line[j][1], line[j][2], line[j][3]);
    }
    ans -= sgt.get(1, 1, n, 1, n);
  }
  
  printf("%d", ans/2);

  fclose(stdin);
  fclose(stdout);
  return 0;
}
